/*!
 *@file	     MB26-S_Drive.c
 *@brief	   MB26-S驱动层功能
 *@copyright Copyright (c) 2023,利尔达物联网技术有限公司
 *           All rights reserved.
 *@author	   Lierda-技术应用组
 *@date      2023-7-20
 *@version   V1.0
 */

#include "MB26-S_Drive.h"
#include "NB-IOT_Ports.h"
#include "mcuInit.h"
#include "log.h"


#define  CHECK_NULL( a )                if( a == NULL ){ Log_Printf( "\r\nPARAS NULL !!!\r\n");  return AT_ERROR; }

/*!
 @brief       串口发送函数
 @param[in]   data：           数据内容
 @param[in]   size：           数据长度
 @param[in]   timeOut：        接收超时时间
 @return 
 */
uint8_t UartSendAt( uint8_t* data, uint16_t size, uint32_t timeOut )
{
		int   res;
		const uint8_t*   buff;
	
		CHECK_NULL( data );
		CHECK_NULL( size );
		CHECK_NULL( timeOut );
	
		memset( ( char* )GetRxBuff( 1, buff ), 0, 512 );   //清空接收缓存
	
		if( 0 == UartTranmist( data, size ) )							 //串口发送成功
		{
				if( true == RecTimeout( timeOut ) )						 //接收超时时间内，收到平台下发的urc
				{
						res = AT_SUCCESS;
				}
				else
				{
						Log_Printf( "Module response timed out !!!" );
						res = AT_TIMEOUT;
				}
		}
		return res;
}


/*!
 @brief       接收超时函数
 @param[in]   time：           接收超时时间
 @return      函数执行结果 
							- false：        接收超时
							- true ：        成功收到数据
 */
bool RecTimeout( uint32_t time )
{
		uint32_t  recordTime   = 0;
	
		CHECK_NULL( time );
	
		recordTime = GetSystemTime( );                      //获取当前系统时间
		while( ( GetSystemTime( ) - recordTime ) < time )   //超时时间内，判断是否接收到模组返回的数据
		{
				if( GetRxFlag( 1 ) == true )                    //接收标志位为true，接收到数据
				{
						SetRxFlag( 1, false );                      //串口1接收标志位置位
						return true;
				}
		}
		return false;
}

/*!
 @brief       用户数据发送函数
 @param[in]   data：           用户待发送数据
 @return      函数执行结果 
							- AT_SUCCESS：   数据发送成功
							- AT_ERROR：     数据发送失败   
 */
uint8_t SendUserData( char* data )
{
		int   rev;
		char  txStr[ 512 ] = "";
		const uint8_t*     buff;
	
		CHECK_NULL( data );
	
		sprintf( txStr, "AT+CTM2MSEND=%s,0\r\n", ( char* )data );             //传入用户待发送数据
		Log_Printf( "\r\n[TX]: %s", txStr ); 	                                //上位机打印发送内容

	  rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 500 );          //串口发送
	
		if( rev == AT_SUCCESS )																						    //收到平台下发的 urc
		{
				SysDelayMs( 3000 );						                                    //等待数据接收完全
			
				if( strstr( ( char* )GetRxBuff( 1, buff ), "+CTM2M:" ) == NULL )	//判断平台是否收到正确数据
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );									        //打印平台下发的内容
		}
		return rev;
}


/*!
 @brief       发送注销平台请求
 @return      函数执行结果 
							- AT_SUCCESS：   注销成功
							- AT_ERROR：     注销失败
 */
uint8_t SendCancelReq( void )
{
		int   rev;
		char  txStr[ 32 ] = "";
		const uint8_t*    buff;
	
		sprintf( txStr, "AT+CTM2MDEREG\r\n" );
		Log_Printf( "\r\n[TX]: %s", txStr );

		rev = UartSendAt( (uint8_t*)txStr, sizeof(txStr), 500 );             //串口发送
	
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 3000 );						                                  //等待数据接收完全
				if( strstr( ( char* )GetRxBuff( 1, buff ), "OK" ) == NULL )	    //判断平台是否收到正确数据
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );									      //打印串口1接收缓存(平台下发)的内容
		}
		return rev;
}


/*!
 @brief       获取SIM卡状态
 @return      函数执行结果 
							- AT_SUCCESS：   SIM卡状态正常
							- AT_ERROR：     SIM卡状态异常
 */
uint8_t GetSimStatus( void )
{
		int   rev;
		char  txStr[ 32 ] = "";
		const uint8_t*    buff;
	
		sprintf( txStr, "AT+CPIN?\r\n" );
		Log_Printf( "\r\n[TX]: %s", txStr ); 
	
	  rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 1000 );         //串口发送
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );						                                   //等待数据接收完全
				if( strstr( ( char* )GetRxBuff( 1, buff ), "READY" ) == NULL )	 //判断平台是否收到正确数据   
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );									       //打印串口1接收缓存(平台下发)的内容
		}
		return rev;
}

/*!
 @brief       模组软复位
 @return      函数执行结果 
							- AT_SUCCESS：   复位成功
							- AT_ERROR：     复位失败
 */
uint8_t ModuleSoftReset( void )
{
		int   rev;
		char  txStr[ 32 ] = "";
		const uint8_t*    buff;
	
		sprintf( txStr, "AT+ECRST\r\n" );
		Log_Printf( "\r\n[TX]: %s", txStr ); 
	
	  rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 500 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );			
				if( strstr( ( char* )GetRxBuff( 1, buff ), "OK" ) == NULL )	
				{
						rev = AT_ERROR;		
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );								
		}
		return rev;
}


/*!
 @brief       模组上电检测
 @return      函数执行结果 
							- AT_SUCCESS：   模组已上电
							- AT_ERROR：     模组未上电
 */
uint8_t AtChecke( void )  
{
		int   rev;
		char  txStr[ 32 ] = "";
		const uint8_t*    buff;
	
		sprintf( txStr, "AT\r\n" );
		Log_Printf( "\r\n[TX]: %s", txStr ); 
	
	  rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 1000 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );			
				if( strstr( ( char* )GetRxBuff( 1, buff ), "OK" ) == NULL )	
				{
						rev = AT_ERROR;		
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );		
		}
		return rev;
}


/*!
 @brief       查询PS域附着状态(网络注册状态)
 @return      函数执行结果 
							- DEVICE_ONLINE：模组已入网
							- DEVICE_ON_NET：模组未入网
 */
uint8_t GetNetStatus( void )
{
		char  *offset     = NULL;
		char  txStr[ 32 ] = "";
		const uint8_t*    buff;
		int   psValue, psValue2, rev;
	
		sprintf( txStr, "AT+CEREG?\r\n" );
		Log_Printf( "\r\n[TX]: %s", txStr ); 
	
		if( AT_SUCCESS == UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 500 ) )
		{
				SysDelayMs( 1000 );		
				Log_Printf( "%s", GetRxBuff( 1, buff ) );                           //打印平台下发数据内容	
			
				if( strstr( ( char* )GetRxBuff( 1, buff ), "+CEREG:" ) != NULL )    //若平台成功接收到数据
				{	
						offset = strstr( ( char* )GetRxBuff( 1, buff ), ":" );
						sscanf( &offset[ 2 ], "%d,%d", &psValue, &psValue2 );

						if( ( psValue2 == 1 )||( psValue2 == 5 ) )                      //判断设备是否入网
						{
								rev = DEVICE_ONLINE;
								Log_Printf( "\r\nDevice online !!!\r\n" );
						}
						else
						{
								Log_Printf( "\r\nDevice not online !!!\r\n" );
								rev = DEVICE_ON_NET;
						}
				}	
		}
		return rev;
}


/*!
 @brief       查询设备IMEI
 @return      函数执行结果 
							- AT_SUCCESS：   获取IMEI成功
							- AT_ERROR：获取IMEI失败
 */
uint8_t GetDeviceImei( void )  
{
		int   rev;
		char  txStr[ 32 ] = "";
		const uint8_t*    buff;
	
		sprintf( txStr, "AT+CGSN=1\r\n" );
		Log_Printf( "\r\n[TX]: %s", txStr ); 
	
	  rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 500 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );					
				if( strstr( ( char* )GetRxBuff( 1, buff ), "+CGSN:" ) == NULL )	
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );							
		}
		return rev;
}


/*!
 @brief       发送注册请求
 @return      函数执行结果 
							- AT_SUCCESS：   注册成功
							- AT_ERROR：     注册失败
 */
uint8_t SendRegReq( void )
{
		int  rev;
		char txStr[ 32 ] = "";
		const uint8_t*   buff;
	
		sprintf( txStr, "AT+CTM2MREG\r\n" );
		Log_Printf( "\r\n[TX]: %s", txStr ); 
	
		rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 500 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 3000 );					
				if( strstr( ( char* )GetRxBuff( 1, buff ), "obsrv,0" ) == NULL )  
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );			
		}
		return rev;
}


/*!
 @brief       配置模组休眠模式
 @param[in]   enable：         开启/禁止修眠
 @param[in]   mode：           休眠等级
 @return      函数执行结果 
							- AT_SUCCESS：   休眠配置成功
							- AT_ERROR：     休眠配置失败
 */
uint8_t SetSleepMode( int enable, int mode )   
{
		int  rev;
		char txStr[ 32 ] = "";
		const uint8_t*   buff;

		sprintf( txStr, "AT+ECPMUCFG=%d,%d\r\n", enable, mode );
		Log_Printf( "\r\n[TX]: %s", txStr );
	
		rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 500 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );				
				if( strstr( ( char* )GetRxBuff( 1, buff ), "OK" ) == NULL )
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );		
		}
		return rev;
} 


/*!
 @brief       配置平台连接参数
 @param[in]   severUrl：       平台连接参数
 @return      函数执行结果 
							- AT_SUCCESS：   连接参数配置成功
							- AT_ERROR：     连接参数失败
 */
uint8_t SetConnePara( char *severUrl ) 
{
		int  rev;
		char txStr[ 64 ] = "";
		const uint8_t*   buff;
	
		CHECK_NULL( severUrl );
	
		sprintf( txStr, "AT+CTM2MSETPM=%s\r\n", severUrl );
		Log_Printf( "\r\n[TX]: %s", txStr ); 
	
		rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 500 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );				
				if( strstr( ( char* )GetRxBuff( 1, buff ), "OK" ) == NULL )	
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );			
		}
		return rev;
}


/*!
 @brief       释放RRC
 @return      函数执行结果 
							- AT_SUCCESS：   RRC释放成功
							- AT_ERROR：     RRC释放失败
 */
uint8_t ReleasRrc( void )
{
		int  rev;
		char txStr[ 32 ] = "";
		const uint8_t*   buff;
	
		sprintf( txStr, "AT+ECNBIOTRAI=1\r\n" );	
		Log_Printf( "\r\n[TX]: %s", txStr ); 

		rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 500 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );			
				if( strstr( ( char* )GetRxBuff( 1, buff ), "OK" ) == NULL )	
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );					
		}
		return rev;
}



/**
 @brief       配置模组PSM功能
 @param[in]   type：           PSM禁用或启用选择，0表示禁用PSM、1表示启用PSM			           
 @param[in]   mode：           配置禁用或启用 PSM
 @param[in]   ctiveTime：      激活时间值
 @return      函数执行结果 
							- AT_SUCCESS：   PSM配置成功
							- AT_ERROR：		 PSM配置失败
 */
uint8_t SetModulePsm( uint8_t mode, char* ctiveTime )
{
		int rev;
		char txStr[ 32 ] = "";
		const uint8_t*   buff;
	
		CHECK_NULL( mode );
	
		if( mode == 1 )            //启用PSM，需要配置模组 TAU 周期(T3412)
		{
				sprintf( txStr, "AT+CPSMS=1,,,,\"%s\"\r\n", ctiveTime );
		}
		if( mode == 0 )            //禁用PSM，无需配置模组 TAU 周期
		{
				sprintf( txStr, "AT+CPSMS=0\r\n" );
		}
		Log_Printf( "\r\n[TX]: %s", txStr ); 
	
		rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 500 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );		
				if( strstr( ( char* )GetRxBuff( 1, buff ), "OK" ) == NULL ) 
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );	
		}
		return rev;
}


/*!
 @brief       关闭模组eDRX功能
 @return      函数执行结果 
							- AT_SUCCESS：   eDRX关闭成功
							- AT_ERROR：     eDRX关闭失败
 */
uint8_t CloseModuleEdrx( void )
{
		int rev;
		char txStr[ 32 ] = "";
		const uint8_t*   buff;
	
		sprintf( txStr, "AT+CEDRXS=0\r\n" );
		Log_Printf( "\r\n[TX]: %s", txStr ); 
	
		rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 1000 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );
				if( strstr( ( char* )GetRxBuff( 1, buff ), "OK" ) == NULL )	
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );		
		}
		return rev;
}


/*!
 @brief       关闭\开启射频和SIM卡
 @return      函数执行结果 
							- AT_SUCCESS：   射频关闭\开启成功
							- AT_ERROR：     射频关闭\开启失败
 */
uint8_t FuncRadio( uint8_t mode )
{
		int  rev;
		char txStr[ 32 ] = "";
		const uint8_t*   buff;
	
		sprintf( txStr, "AT+CFUN=%d\r\n", mode );
		Log_Printf( "\r\n[TX]: %s", txStr ); 
	
		rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 1000 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );			
				if( strstr( ( char* )GetRxBuff( 1, buff ), "OK" ) == NULL )
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );							
		}
		return rev;
}


/*!
 @brief       清除频点
 @return      函数执行结果 
							- AT_SUCCESS：   频点清除成功
							- AT_ERROR：     频点清除失败
 */
uint8_t ClearFreq( void )
{
		int  rev         = -1;
		char txStr[ 32 ] = "";
		const uint8_t*   buff;
	
		sprintf( txStr, "AT+ECFREQ=3\r\n" );
		Log_Printf( "\r\n[TX]: %s", txStr ); 
	
		rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 1000 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );			
				if( strstr( ( char* )GetRxBuff( 1, buff ), "OK" ) == NULL )	
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );	
		}
		return rev;
}



/*!
 @brief       驻网（若为兼容海思版本，异常处理流程中加入此步骤）
 @return      函数执行结果 
							- AT_SUCCESS：   驻网成功
							- AT_ERROR：     驻网失败
 */
uint8_t RegNetwork( void )
{
		int  rev;
		char txStr[ 32 ] = "";
		const uint8_t*   buff;
	
		sprintf( txStr, "AT+CGATT=1\r\n" );
		Log_Printf( "\r\n[TX]: %s", txStr ); 

		rev = UartSendAt( ( uint8_t* )txStr, sizeof( txStr ), 500 );
		if( rev == AT_SUCCESS )
		{
				SysDelayMs( 1000 );				 
				if( strstr( ( char* )GetRxBuff( 1, buff ), "OK" ) == NULL )	 
				{
						rev = AT_ERROR;
				}
				Log_Printf( "%s", GetRxBuff( 1, buff ) );				 
		}
		return rev;
}


				

	




